#pragma once

namespace hHashMapDetail
{
	template <typename Key, typename Val, typename Hash, bool IsConst>
	class Iterator
	{
		friend hHashMap<Key, Val, Hash>;
		friend Node<Key, Val, Hash>;

		using Map = std::conditional_t<IsConst, const hHashMap<Key, Val, Hash>, hHashMap<Key, Val, Hash>>;
		using Node = std::conditional_t<IsConst, const Node<Key, Val, Hash>, Node<Key, Val, Hash>>;
		using PNodePtr = std::shared_ptr<Node*>;
		using KeyRef = std::reference_wrapper<const Key>;
		using ValRef = std::reference_wrapper<std::conditional_t<IsConst, const Val, Val>>;
		using RetPr = std::pair<KeyRef, ValRef>;
		using RetPrPtr = std::shared_ptr<RetPr>;

		PNodePtr _ppNode;
	public:
		Iterator(PNodePtr ppNode = PNodePtr()) : _ppNode(ppNode) {}

		auto operator->()->RetPrPtr;
		auto operator*()->RetPr;
		auto operator++()->Iterator&;
		auto operator++(int)->Iterator;

		bool operator==(const Iterator& other) const;
		bool operator!=(const Iterator& other) const { return !(*this == other); }
		operator bool() const;

		auto& get() { return _ppNode; }
	};
}
